home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / system / ms_sh22b.zip / src / glob.c < prev    next >
C/C++ Source or Header  |  1993-12-01  |  17KB  |  766 lines

  1. /* MS-DOS GLOB (3C) FUNCTION
  2.  *
  3.  * MS-DOS GLOB FUNCTION - Copyright (c) 1990,1,2 Data Logic Limited.
  4.  *
  5.  * This code is subject to the following copyright restrictions:
  6.  *
  7.  * 1.  Redistribution and use in source and binary forms are permitted
  8.  *     provided that the above copyright notice is duplicated in the
  9.  *     source form.
  10.  *
  11.  *    $Header: /usr/users/istewart/src/shell/sh2.2/RCS/glob.c,v 2.1 1993/06/14 10:59:32 istewart Exp $
  12.  *
  13.  *    $Log: glob.c,v $
  14.  * Revision 2.1  1993/06/14  10:59:32  istewart
  15.  * More changes for 223 beta
  16.  *
  17.  * Revision 2.0  1992/04/13  17:39:09  Ian_Stewartson
  18.  * MS-Shell 2.0 Baseline release
  19.  *
  20.  */
  21.  
  22. #include <sys/types.h>            /* MS-DOS type definitions      */
  23. #include <sys/stat.h>            /* File status definitions    */
  24. #include <stdio.h>            /* Standard I/O delarations     */
  25. #include <stdlib.h>            /* Standard library functions   */
  26. #include <string.h>            /* String library functions     */
  27. #include <limits.h>            /* String library functions     */
  28. #include <dirent.h>            /* Direction I/O functions    */
  29. #include <ctype.h>            /* Character types function    */
  30. #include <unistd.h>            /* Other functions        */
  31.  
  32. #ifdef __TURBOC__
  33. #  include <alloc.h>            /* Malloc functions        */
  34. #  include <dir.h>            /* Dos directory functions    */
  35. #else
  36. #  include <malloc.h>            /* Malloc functions        */
  37. #endif
  38.  
  39. #include <glob.h>
  40.  
  41. #if defined (MSDOS) || defined (__OS2__) || defined (__TURBOC__)
  42. #  if defined (OS2) || defined (__OS2__)
  43.  
  44. #    define INCL_DOSDEVICES
  45. #    define INCL_DOSMISC
  46. #    include <os2.h>            /* OS2 functions declarations       */
  47.  
  48. #    if defined (__OS2__)
  49. #      define DISABLE_HARD_ERRORS    DosError (FERR_DISABLEHARDERR)
  50. #      define ENABLE_HARD_ERRORS    DosError (FERR_ENABLEHARDERR)
  51. #    else
  52. #      define DISABLE_HARD_ERRORS    DosError (HARDERROR_DISABLE)
  53. #      define ENABLE_HARD_ERRORS    DosError (HARDERROR_ENABLE)
  54. #    endif
  55.  
  56. #  else
  57. #    include <bios.h>            /* DOS BIOS functions        */
  58. #    include <dos.h>            /* DOS functions        */
  59. #    define DISABLE_HARD_ERRORS
  60. #    define ENABLE_HARD_ERRORS
  61. #  endif
  62. #endif
  63.  
  64. /*
  65.  * OS/2 2.x has these missing
  66.  */
  67.  
  68. #ifndef S_IFMT
  69. #  define    S_IFMT    0xf000    /* type of file                */
  70. #endif
  71.  
  72. #ifndef S_ISDIR
  73. #  define S_ISDIR(m)    ((((m) & S_IFMT) == S_IFDIR))
  74. #endif
  75.  
  76. /*
  77.  * Functions
  78.  */
  79.  
  80. static int    _GP_SortCompare        _PROTO ((char **, char **));
  81. static int    _GP_ExpandField        _PROTO ((char *, char *, glob_t *));
  82. static int    _GP_ExpandMetaCharacters _PROTO ((char *, glob_t *));
  83. static int    _GP_AddArgument        _PROTO ((char *, glob_t *));
  84. static bool    _GP_MatchPattern    _PROTO ((char *, char *));
  85. static bool    _GP_access        _PROTO ((char *, int));
  86. static bool    _GP_stat        _PROTO ((char *, struct stat *));
  87.  
  88. static char    *_GP_MetaChars = "?*[\\";
  89. static char    *_GP_NullString = "";
  90.  
  91. #ifdef MSDOS
  92. static    int    _GP_GetNumberofFloppyDrives (void);
  93.  
  94. #if defined (OS2) || defined (__OS2__) || defined (__TURBOC__)
  95. static void     _dos_setdrive (unsigned int, unsigned int *);
  96. static void     _dos_getdrive (unsigned int *);
  97. #endif
  98.  
  99. static char    *_GP_CheckForMultipleDrives    _PROTO ((char *));
  100. #endif
  101.  
  102. /*
  103.  * There appears to be no alloca in TurboC
  104.  */
  105.  
  106. #ifdef __TURBOC__
  107. #  define alloca(x)        malloc (x)
  108. #  define alloca_free(x)    free (x)
  109. #else
  110. #  define alloca_free(x)
  111. #endif
  112.  
  113. /*
  114.  * Free up space
  115.  */
  116.  
  117. void    globfree (gp)
  118. glob_t    *gp;
  119. {
  120.     int        i = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
  121.  
  122.     while (i < gp->gl_pathc)
  123.     free (gp->gl_pathv[i++]);
  124.  
  125.     free (gp->gl_pathv);
  126. }
  127.  
  128. /* Main search function */
  129.  
  130. int    glob (Pattern, flags, ErrorFunction, gp)
  131. char    *Pattern;
  132. int    flags;
  133. int    (*ErrorFunction) _PROTO ((char *, int));
  134. glob_t    *gp;
  135. {
  136.     int        ReturnValue;
  137.     char    *PatternCopy;
  138.     char    *cp;
  139.  
  140. /* If no append mode - initialise */
  141.  
  142.     if (!(flags & GLOB_APPEND))
  143.     {
  144.     gp->gl_pathc = 0;
  145.     gp->gl_pathv = (char **)NULL;
  146.     }
  147.  
  148.     gp->gl_flags = flags;
  149.     gp->gl_ef = ErrorFunction;
  150.  
  151.     if ((PatternCopy = alloca (strlen (Pattern) + 1)) == (char *)NULL)
  152.     return GLOB_NOSPACE;
  153.  
  154. /* Expand and kill environment */
  155.  
  156.     if (ReturnValue = _GP_ExpandMetaCharacters (strcpy (PatternCopy, Pattern),
  157.                         gp))
  158.     {
  159.     alloca_free (PatternCopy);
  160.     return ReturnValue;
  161.     }
  162.  
  163. /* Check for no finds.  If add value, strip out \ from the string */
  164.  
  165.     if ((gp->gl_pathc == 0) && (flags & GLOB_NOCHECK))
  166.     {
  167.     cp = strcpy (PatternCopy, Pattern);
  168.  
  169.     while ((cp = strpbrk (cp, "?*[")) != (char *)NULL)
  170.     {
  171.         if ((cp == PatternCopy) || (*(cp - 1) != '\\'))
  172.         cp++;
  173.  
  174.         else
  175.         memmove (cp - 1, cp, strlen (cp) + 1);
  176.     }
  177.  
  178.     if (ReturnValue = _GP_AddArgument (PatternCopy, gp))
  179.     {
  180.         alloca_free (PatternCopy);
  181.         return ReturnValue;
  182.     }
  183.     }
  184.  
  185. /* Terminate string */
  186.  
  187.     if ((gp->gl_pathc != 0) &&
  188.     (ReturnValue = _GP_AddArgument ((char *)NULL, gp)))
  189.     {
  190.     alloca_free (PatternCopy);
  191.     return ReturnValue;
  192.     }
  193.  
  194. /* Get the sort length */
  195.  
  196.     ReturnValue = (gp->gl_flags & GLOB_DOOFFS) ? gp->gl_offs : 0;
  197.  
  198.     if ((!(flags & GLOB_NOSORT)) && (gp->gl_pathc > 1))
  199.     qsort (&gp->gl_pathv[ReturnValue], gp->gl_pathc, sizeof (char *),
  200.         _GP_SortCompare);
  201.  
  202.     alloca_free (PatternCopy);
  203.     return 0;
  204. }
  205.  
  206. /* Compare function for sort */
  207.  
  208. static int    _GP_SortCompare (a1, a2)
  209. char        **a1, **a2;
  210. {
  211.     return strcmp (*a1, *a2);
  212. }
  213.  
  214. /* Expand a field if it has metacharacters in it */
  215.  
  216. static int    _GP_ExpandField (CurrentDirectoryPattern, AppendString, gp)
  217. char        *CurrentDirectoryPattern;    /* Prefix field        */
  218. char        *AppendString;            /* Postfix field        */
  219. glob_t        *gp;
  220. {
  221.     int         i;
  222.     int            ReturnValue = 0;    /* Return Value        */
  223.     char        *FullFileName;        /* Search file name    */
  224.     char        *FileNameStart;
  225.     char        *MatchString;        /* Match string        */
  226.     DIR            *DirHandler;
  227.     struct dirent    *CurrentDirectoryEntry;
  228. #ifdef MSDOS
  229.     unsigned int    CurrentDrive;        /* Current drive    */
  230.     unsigned int    MaxDrives;        /* Max drive        */
  231.     unsigned int    SelectedDrive;        /* Selected drive    */
  232.     unsigned int    x_drive, y_drive;    /* Dummies        */
  233.     char        *DriveCharacter;    /* Multi-drive flag    */
  234.     char        SDriveString[2];
  235.  
  236. /* Convert file name to lower case */
  237.  
  238. #if defined (OS2) || defined (__OS2__)
  239.     if (!IsHPFSFileSystem (CurrentDirectoryPattern))
  240.     strlwr (CurrentDirectoryPattern);
  241. #else
  242.     strlwr (CurrentDirectoryPattern);
  243. #endif
  244.  
  245. /* Search all drives ? */
  246.  
  247.     if ((DriveCharacter = _GP_CheckForMultipleDrives (CurrentDirectoryPattern))
  248.         != (char *)NULL)
  249.     {
  250.     _dos_getdrive (&CurrentDrive);    /* Get number of drives        */
  251.     _dos_setdrive (CurrentDrive, &MaxDrives);
  252.     SDriveString[1] = 0;
  253.  
  254.     for (SelectedDrive = 1; SelectedDrive <= MaxDrives; ++SelectedDrive)
  255.     {
  256.         _dos_setdrive (SelectedDrive, &x_drive);
  257.         _dos_getdrive (&y_drive);
  258.         _dos_setdrive (CurrentDrive, &x_drive);
  259.  
  260. /* Check to see if the second diskette drive is really there */
  261.  
  262.         if ((_GP_GetNumberofFloppyDrives () < 2) && (SelectedDrive == 2))
  263.         continue;
  264.  
  265. /* If the drive exists and is in our list - process it */
  266.  
  267.         *DriveCharacter = 0;
  268.         *SDriveString = (char)(SelectedDrive + 'a' - 1);
  269.         strlwr (CurrentDirectoryPattern);
  270.  
  271.         if ((y_drive == SelectedDrive) &&
  272.         _GP_MatchPattern (SDriveString, CurrentDirectoryPattern))
  273.         {
  274.         if ((FullFileName = alloca (strlen (DriveCharacter) + 3))
  275.                 == (char *)NULL)
  276.             return GLOB_NOSPACE;
  277.  
  278.         *DriveCharacter = ':';
  279.         *FullFileName = *SDriveString;
  280.         strcpy (FullFileName + 1, DriveCharacter);
  281.  
  282.         i = _GP_ExpandField (FullFileName, AppendString, gp);
  283.         alloca_free (FullFileName);
  284.  
  285.         if (i)
  286.             return i;
  287.         }
  288.  
  289.         *DriveCharacter = ':';
  290.     }
  291.  
  292.     return 0;
  293.     }
  294. #endif
  295.  
  296. /* Get the path length */
  297.  
  298.     MatchString = strrchr (CurrentDirectoryPattern, '/');
  299. #ifdef MSDOS
  300.     if ((MatchString == (char *)NULL) &&
  301.     (*(CurrentDirectoryPattern + 1) == ':'))
  302.     MatchString = CurrentDirectoryPattern + 1;
  303. #endif
  304.  
  305. /* Set up file name for search */
  306.  
  307.     if ((MatchString == (char *)NULL) || (*MatchString == ':'))
  308.     {
  309.     if ((FullFileName = alloca (NAME_MAX + 7 +
  310.                     strlen (AppendString))) == (char *)NULL)
  311.         return GLOB_NOSPACE;
  312.  
  313.     if (MatchString != (char *)NULL)
  314.         *(strcpy (FullFileName, "x:.")) = *CurrentDirectoryPattern;
  315.  
  316.     else
  317.         strcpy (FullFileName, ".");
  318.  
  319.     FileNameStart = FullFileName +
  320.             (int)((MatchString != (char *)NULL) ? 2 : 0);
  321.     }
  322.  
  323. /* Case of /<directory>/... */
  324.  
  325.     else if ((FullFileName = alloca (NAME_MAX + 4 + strlen (AppendString)